"""Compare test results against a previously saved set of results to find differences.
"""

import os
import sys
import logging

from django.core import serializers

from browsertests.utils import cli_wrapper
from browsertests.results.models import Result

log = logging.getLogger(__name__)

TEST_IDS = [
    "unit/crashers/crash_firefox_trunk_20081110.svg",
    "unit/crashers/crash_opera_962_win.html",
    "unit/layouttests/dumpAsText.html",
    "unit/layouttests/dumpChildFrames.html",
    "unit/layouttests/failure.html",
    "unit/layouttests/frameDump.html",
    "unit/layouttests/frameNoDump.html",
    "unit/layouttests/innerText/blank.html",
    "unit/layouttests/innerText/blocks-css.html",
    "unit/layouttests/innerText/blocks.html",
    "unit/layouttests/innerText/br.html",
    "unit/layouttests/innerText/css-dom-read.html",
    "unit/layouttests/innerText/css-selector-text.html",
    "unit/layouttests/innerText/hidden.html",
    "unit/layouttests/innerText/inlines.html",
    "unit/layouttests/innerText/script.html",
    "unit/layouttests/innerText/simple.html",
    "unit/layouttests/innerText/tables-1.html",
    "unit/layouttests/noDumpChildFrames.html",
    "unit/layouttests/notifyDone.html",
    "unit/layouttests/timeout.html",
    "unit/layouttests/waitUntilDoneOnload.html",
    "unit/layout_fail.html",
    "unit/layout_pass.html",
    "unit/reftest:2ec9064e43b7ddd48e95a40ecf08f94d",
    "unit/reftest:59259f892b417b0917b537108dbeeeaa",
    "unit/reftest:a358677320a39f95933c35601cec2cf0",
    "unit/reftest:bae27c26cafeb1f84bfeedb65c79a503",
    "unit/reftest:d11397392461e981585aee60a2241777",
    "unit/test_alerts.html",
    "unit/test_mochi_fail.html",
    "unit/test_mochi_mochikit_json_bug.html",
    "unit/test_mochi_pass.html",
    "unit/vertical_tab.html",
]

def get_results():
    return Result.objects.filter(test__pk__in=TEST_IDS)

def check_regress(action, fixture):
    if action == "save":
        json = serializers.serialize("json", get_results(), indent=2)
        open(fixture, "w").write(json)
    elif action == "reset":
        get_results().delete()
    elif action == "check":
        expected_results = [r.object for r in serializers.deserialize("json", open(fixture).read())]
        results = get_results()
        print "results count: %s, expected results count: %s" % (len(results), len(expected_results))
        failed = False
        if len(results) != len(expected_results):
            print "ERROR: expected and actual results count does not match"
            failed = True

        test_ua_to_result = {}
        test_ua_to_expected_result = {}

        def test_ua_key(result):
            return "%s_%s" % (result.test_id, result.ua_id)

        for result in results:
            test_ua_to_result[test_ua_key(result)] = result
        for expected_result in expected_results:
            test_ua_to_expected_result[test_ua_key(expected_result)] = expected_result

        IGNORED_PROPS = ["session", "duration", "date", "id", "saved_path", "test_version"]

        for (key, expected_result) in test_ua_to_expected_result.iteritems():
            result = test_ua_to_result.get(key)

            if not result:
                failed = True
                print "ERROR: no result for key %s" % key
                continue

            for p in result.__dict__.keys():
                if p.startswith("_") or p in IGNORED_PROPS:
                    continue
                expected = getattr(expected_result, p)
                if expected == None or expected == "":
                    continue
                if not getattr(result, p) == expected:
                    failed = True
                    print "ERROR: Unexpected value for result: %s" % result
                    print "  Property: %s, actual: %s, expected: %s" % (p, repr(getattr(result, p)), repr(getattr(expected_result, p)))

        if failed:
            print "FAILURE: regression detected"
            sys.exit(2)
        print "SUCCESS: no regression found"
    else:
        raise Exception("Invalid action")

def main():
    from optparse import OptionParser
    usage = "%prog [OPTIONS] {save|reset|check} FIXTURE_FILE"
    parser = OptionParser(usage=usage)

    parser = cli_wrapper.add_common_parser_options(parser)
    options, args = parser.parse_args()

    if len(args) != 2 or not args[0] in ["save", "reset", "check"]:
        parser.print_help()
        sys.exit(2)

    action, fixture = args
    cli_wrapper.process_options(options)

    check_regress(action, fixture)

if __name__ == "__main__":
    main()
